home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / cug236 / bawksym.c < prev    next >
Text File  |  1980-01-02  |  9KB  |  436 lines

  1. /*
  2.     HEADER:        CUG000.00;
  3.     TITLE:        BAWK Support Module;
  4.     DATE:        05/17/1987;
  5.     VERSION:    1.1;
  6.     FILENAME:    BAWKSYM.C;
  7.     SEE-ALSO:    BAWK.C;
  8.     AUTHORS:    W. C. Colley III, B. Brodt;
  9. */
  10.  
  11. /*
  12.  * Bawk C actions builtin functions, variable declaration, and
  13.  * stack management routines.
  14.  */
  15. #include <stdio.h>
  16. #include "bawk.h"
  17.  
  18. #define MAXARGS        10    /* max # of arguments to a builtin func */
  19. #define F_PRINTF    1
  20. #define F_GETLINE    2
  21. #define F_STRLEN    3
  22. #define F_STRCPY    4
  23. #define F_STRCMP    5
  24. #define F_TOUPPER    6
  25. #define F_TOLOWER    7
  26. #define F_MATCH        8
  27. #define F_NEXTFILE    9
  28.  
  29. /* Functions that are local to this module.    */
  30.  
  31. VARIABLE *decl();
  32.  
  33. int isfunction( s )
  34. char *s;
  35. {
  36.     /*
  37.      * Compare the string "s" to a list of builtin functions
  38.      * and return its (non-zero) token number.
  39.      * Return zero if "s" is not a function.
  40.      */
  41.     if ( !strcmp( s, "printf" ) )
  42.         return F_PRINTF;
  43.     if ( !strcmp( s, "getline" ) )
  44.         return F_GETLINE;
  45.     if ( !strcmp( s, "strlen" ) )
  46.         return F_STRLEN;
  47.     if ( !strcmp( s, "strcpy" ) )
  48.         return F_STRCPY;
  49.     if ( !strcmp( s, "strcmp" ) )
  50.         return F_STRCMP;
  51.     if ( !strcmp( s, "toupper" ) )
  52.         return F_TOUPPER;
  53.     if ( !strcmp( s, "tolower" ) )
  54.         return F_TOLOWER;
  55.     if ( !strcmp( s, "match" ) )
  56.         return F_MATCH;
  57.     if ( !strcmp( s, "nextfile" ) )
  58.         return F_NEXTFILE;
  59.     return 0;
  60. }
  61.  
  62. int iskeyword( s )
  63. char *s;
  64. {
  65.     /*
  66.      * Compare the string "s" to a list of keywords and return its
  67.      * (non-zero) token number.  Return zero if "s" is not a keyword.
  68.      */
  69.     if ( !strcmp( s, "char" ) )
  70.         return T_CHAR;
  71.     if ( !strcmp( s, "int" ) )
  72.         return T_INT;
  73.     if ( !strcmp( s, "if" ) )
  74.         return T_IF;
  75.     if ( !strcmp( s, "else" ) )
  76.         return T_ELSE;
  77.     if ( !strcmp( s, "while" ) )
  78.         return T_WHILE;
  79.     if ( !strcmp( s, "break" ) )
  80.         return T_BREAK;
  81.  
  82.     if ( !strcmp( s, "NF" ) )
  83.         return T_NF;
  84.     if ( !strcmp( s, "NR" ) )
  85.         return T_NR;
  86.     if ( !strcmp( s, "FS" ) )
  87.         return T_FS;
  88.     if ( !strcmp( s, "RS" ) )
  89.         return T_RS;
  90.     if ( !strcmp( s, "FILENAME" ) )
  91.         return T_FILENAME;
  92.     if ( !strcmp( s, "BEGIN" ) )
  93.         return T_BEGIN;
  94.     if ( !strcmp( s, "END" ) )
  95.         return T_END;
  96.     return 0;
  97. }
  98.  
  99. void function(funcnum)
  100. int funcnum;
  101. {
  102.     int argc;
  103.     char lpar;
  104.     DATUM args[MAXARGS];
  105.  
  106.     argc = 0;
  107.     if (Token == T_LPAREN) {
  108.         lpar = 1;  getoken();
  109.     }
  110.     else lpar = 0;
  111.     /*
  112.      * If there are any arguments, evaluate them and copy their values
  113.      * to a local array.
  114.      */
  115.     if (Token != T_RPAREN && Token != T_EOF) {
  116.         for (;;) {
  117.             expression();
  118.             if (argc < MAXARGS) args[argc++].ival = popint();
  119.             else popint();
  120.             if (Token == T_COMMA) getoken();
  121.             else break;
  122.         }
  123.     }
  124.     if (lpar && Token != T_RPAREN) error( "missing ')'", ACT_ERROR );
  125.     else if (Token == T_RPAREN) getoken();
  126.  
  127.     switch (funcnum) {
  128.            case F_PRINTF:  /* just like the real printf() function */
  129.             pushint(printf(args[0].dptr,args[1].ival,args[2].ival,
  130.             args[3].ival,args[4].ival,args[5].ival, args[6].ival,
  131.             args[7].ival,args[8].ival,args[9].ival));
  132.             break;
  133.            case F_GETLINE:
  134.         /*
  135.          * Get the next line of input from the current input file
  136.          * and parse according to the current field seperator.
  137.          * Don't forget to free up the previous line's words first...
  138.          */
  139.             while (Fieldcount) free(Fields[--Fieldcount]);
  140.             pushint(getline());
  141.             Fieldcount = parse(Linebuf,Fields,Fldsep);
  142.             break;
  143.            case F_STRLEN:  /* calculate length of string argument */
  144.             pushint(strlen(args[0].dptr));
  145.             break;
  146.            case F_STRCPY:  /* copy second string to first string */
  147.             pushint((int)strcpy(args[0].dptr,args[1].dptr));
  148.             break;
  149.            case F_STRCMP:  /* compare two strings */
  150.             pushint(strcmp(args[0].dptr,args[1].dptr));
  151.             break;
  152.            case F_TOUPPER: /* convert character argument to upper case */
  153.             pushint(toupper(args[0].ival));
  154.             break;
  155.            case F_TOLOWER: /* convert character argument to lower case */
  156.             pushint(tolower(args[0].ival));
  157.             break;
  158.            case F_MATCH:   /* match string argument to regular expr. */
  159.             pushint(match(args[0].dptr,args[1].dptr));
  160.             break;
  161.            case F_NEXTFILE:/* close current input file, process next */
  162.             endfile();    pushint(0);
  163.             break;
  164.            default:           /* oops! */
  165.             error("bad function call",ACT_ERROR);
  166.     }
  167. }
  168.  
  169. VARIABLE *findvar( s )
  170. char *s;
  171. {
  172.     /*
  173.      * Search the symbol table for a variable whose name is "s".
  174.      */
  175.     VARIABLE *pvar;
  176.     int i;
  177.     char name[ MAXVARLEN ];
  178.  
  179.     i = 0;
  180.     while ( i < MAXVARLEN && alphanum( *s ) )
  181.         name[i++] = *s++;
  182.     if ( i<MAXVARLEN )
  183.         name[i] = 0;
  184.  
  185.     for ( pvar = Vartab; pvar<Nextvar; ++pvar )
  186.     {
  187.         if ( !strncmp( pvar->vname, name, MAXVARLEN ) )
  188.             return pvar;
  189.     }
  190.     return NULL;
  191. }
  192.  
  193. VARIABLE *addvar( name )
  194. char *name;
  195. {
  196.     /*
  197.      * Add a new variable to symbol table and assign it default
  198.      * attributes (int name;)
  199.      */
  200.     int i;
  201.  
  202.     if ( Nextvar <= Vartab + MAXVARTABSZ )
  203.     {
  204.         i = 0;
  205.         while ( i<MAXVARLEN && alphanum( *name ) )
  206.             Nextvar->vname[i++] = *name++;
  207.         if ( i<MAXVARLEN )
  208.             Nextvar->vname[i] = 0;
  209.  
  210.         Nextvar->vclass = 0;
  211.         Nextvar->vsize = WORD;
  212.         Nextvar->vlen = 0;
  213.         /*
  214.          * Allocate some new room
  215.          */
  216.         Nextvar->vptr = getmem( WORD );
  217.         fillmem( Nextvar->vptr, WORD, 0 );
  218.     }
  219.     else
  220.         error( "symbol table overflow", MEM_ERROR );
  221.  
  222.     return Nextvar++;
  223. }
  224.  
  225. void declist()
  226. {
  227.     /*
  228.      * Parse a "char" or "int" statement.
  229.      */
  230.     char type;
  231.  
  232.     type = Token;
  233.     getoken();
  234.     decl( type );
  235.     while ( Token==T_COMMA )
  236.     {
  237.         getoken();
  238.         decl( type );
  239.     }
  240.     if ( Token==T_SEMICOLON )
  241.         getoken();
  242. }
  243.  
  244. VARIABLE *decl( type )
  245. int type;
  246. {
  247.     /*
  248.      * Parse an element of a "char" or "int" declaration list.
  249.      * The function stmt_compile() has already entered the variable
  250.      * into the symbol table as an integer, this routine simply changes
  251.      * the symbol's class, size or length according to the declaraction.
  252.      * WARNING: The interpreter depends on the fact that pointers are
  253.      * the same length as int's.  If your machine uses long's for
  254.      * pointers either change the code or #define int long (or whatever).
  255.      */
  256.     char class, size;
  257.     int len;
  258.     unsigned oldsize, newsize;
  259.     VARIABLE *pvar;
  260.  
  261.     if ( Token==T_MUL )
  262.     {
  263.         /*
  264.          * it's a pointer
  265.          */
  266.         getoken();
  267.         pvar = decl( type );
  268.         ++pvar->vclass;
  269.     }
  270.     else if ( Token==T_VARIABLE )
  271.     {
  272.         /*
  273.          * Simple variable so far.  The token value (in the global
  274.          * "Value" variable) is a pointer to the variable's symbol
  275.          * table entry.
  276.          */
  277.         pvar = (VARIABLE *)Value.dptr;
  278.         getoken();
  279.         class = 0;
  280.         /*
  281.          * Compute its length
  282.          */
  283.         if ( Token==T_LBRACKET )
  284.         {
  285.             /*
  286.              * It's an array.
  287.              */
  288.             getoken();
  289.             ++class;
  290.             /*
  291.              * Compute the dimension
  292.              */
  293.             expression();
  294.             if ( Token!=T_RBRACKET )
  295.                 error( "missing ']'", ACT_ERROR );
  296.             getoken();
  297.             len = popint();
  298.         }
  299.         else
  300.             /*
  301.              * It's a simple variable - array length is zero.
  302.              */
  303.             len = 0;
  304.  
  305.         size = (type==T_CHAR) ? BYTE : WORD;
  306.  
  307.         newsize = (len ? len : 1) * size;
  308.         oldsize = (pvar->vlen ? pvar->vlen : 1) * pvar->vsize;
  309.         if ( newsize != oldsize )
  310.         {
  311.             /*
  312.              * The amount of storage needed for the variable
  313.              * has changed - free up memory allocated initially
  314.              * and reallocate for new size.
  315.              */
  316.             free( pvar->vptr );
  317.             pvar->vptr = getmem( newsize );
  318.         }
  319.         /*
  320.          * Now change the variable's attributes.
  321.          */
  322.         pvar->vclass = class;
  323.         pvar->vsize = size;
  324.         pvar->vlen = len;
  325.     }
  326.     else
  327.         syntaxerror();
  328.  
  329.     return pvar;
  330. }
  331.  
  332. void assignment()
  333. {
  334.     /*
  335.      * Perform an assignment
  336.      */
  337.     int ival;
  338.  
  339.     ival = popint();
  340.     /*
  341.      * make sure we've got an lvalue
  342.      */
  343.     if ( Stackptr->lvalue )
  344.     {
  345.         if ( Stackptr->class )
  346.             movemem( &ival, Stackptr->value.dptr, WORD );
  347.         else
  348.             movemem(&ival, Stackptr->value.dptr, Stackptr->size);
  349.         pop();
  350.         pushint( ival );
  351.     }
  352.     else
  353.         error( "'=' needs an lvalue", ACT_ERROR );
  354. }
  355.  
  356. int pop()
  357. {
  358.     /*
  359.      * Pop the stack and return the integer value
  360.      */
  361.     if ( Stackptr >= Stackbtm )
  362.         return (Stackptr--)->value.ival;
  363.     error( "stack underflow", ACT_ERROR );
  364.     return 0;
  365. }
  366.  
  367. void push( pclass, plvalue, psize, pdatum )
  368. char pclass, plvalue, psize;
  369. DATUM *pdatum;
  370. {
  371.     /*
  372.      * Push item parts onto the stack
  373.      */
  374.     if ( ++Stackptr <= Stacktop )
  375.     {
  376.         Stackptr->lvalue = plvalue;
  377.         Stackptr->size = psize;
  378.         if ( !(Stackptr->class = pclass)  &&  !plvalue )
  379.             Stackptr->value.ival = pdatum->ival;
  380.         else
  381.             Stackptr->value.dptr = pdatum->dptr;
  382.     }
  383.     else
  384.         error( "stack overflow", MEM_ERROR );
  385. }
  386.  
  387. void pushint( intvalue )
  388. int intvalue;
  389. {
  390.     /*
  391.      * push an integer onto the stack
  392.      */
  393.     if ( ++Stackptr <= Stacktop )
  394.     {
  395.         Stackptr->lvalue =
  396.         Stackptr->class = 0;
  397.         Stackptr->size = WORD;
  398.         Stackptr->value.ival = intvalue;
  399.     }
  400.     else
  401.         error( "stack overflow", MEM_ERROR );
  402. }
  403.  
  404. int popint()
  405. {
  406.     /*
  407.      * Resolve the item on the top of the stack and return it
  408.      */
  409.     int intvalue;
  410.  
  411.     if ( Stackptr->lvalue )
  412.     {
  413.         /*
  414.          * if it's a byte indirect, sign extend it
  415.          */
  416.         if ( Stackptr->size == BYTE && !Stackptr->class )
  417.             intvalue = *Stackptr->value.dptr;
  418.         else
  419.         {
  420.             /*
  421.              * otherwise, it's an unsigned int
  422.              */
  423.             intvalue = *(int *)Stackptr->value.dptr;
  424.         }
  425.         pop();
  426.         return intvalue;
  427.     }
  428.     else
  429.     {
  430.         /*
  431.          * else it's an ACTUAL, just pop it
  432.          */
  433.         return pop();
  434.     }
  435. }
  436.